package com.coalmine.api.util;

import com.alibaba.fastjson.JSON;
import com.coalmine.api.common.ResponseDto;
import com.coalmine.api.domain.ApiConfig;
import com.coalmine.api.domain.ApiDatasource;
import com.coalmine.api.domain.ApiSql;
import com.coalmine.common.exception.ServiceException;
import com.coalmine.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
public class RedisPoolManager {
    //所有数据源的连接池存在map里
    static ConcurrentHashMap<String, JedisPool> map = new ConcurrentHashMap<>();

    //获取数据库连接池对象
    public static JedisPool getRedisConnectionPool(ApiDatasource ads) {
        if (map.containsKey(ads.getId())) {
            return map.get(ads.getId());
        } else {
            //获取ip和端口
            HashMap<String, String> s = getIpPortOfStr(ads.getUrl());
            int in = Integer.parseInt(s.get("index"));
            // 获取连接池配置对象
            JedisPoolConfig config = new JedisPoolConfig();
            // 设置最大连接数
            config.setMaxTotal(500);
            //获取连接时的最大等待毫秒数
            config.setMaxWaitMillis(10 * 1000);
            // 设置最大的空闲连接数
            config.setMaxIdle(100);
            // 设置最小的空闲连接数
            config.setMinIdle(10);
            //从池中获取连接时是否测试连接的有效性,默认false
            config.setTestOnBorrow(true);
            config.setTestOnCreate(false);
            //密码
            String pw = null;
            try {
                //如果
                String sting = DESUtils.decrypt(ads.getPassword());
                if (!StringUtils.equals(sting, "0")) {
                    pw = sting;
                }
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
            // 获得连接池:
            //JedisPool(GenericObjectPoolConfig<Jedis> poolConfig, String host, int port, int timeout, String password, int database)
            JedisPool jedisPool = new JedisPool(config,s.get("ip"),Integer.parseInt(s.get("port")),4000, pw,Integer.parseInt(s.get("index")));
            map.put(ads.getId(), jedisPool);
            log.info("create redis datasource：{}", ads.getName());
            return map.get(ads.getId());

        }
    }

    //删除数据库连接池
    public static void removeRedisConnectionPool(String id) {
        if (map.containsKey(id)) {
            JedisPool old = map.get(id);
            map.remove(id);
            old.close();
            log.info("remove redis datasource:", id);
        }
    }

    public static Jedis getRedisPooledConnection(ApiDatasource ads)  {
        //获取连接池对象
        JedisPool pool = RedisPoolManager.getRedisConnectionPool(ads);
        //获取连接
        Jedis jedis = pool.getResource();
//        log.info("获取redis连接成功");
        return jedis;
    }

    //获取redis的url中的IP和端口，以及数据库下标
    public static HashMap<String,String> getIpPortOfStr(String s) {
        //校验地址中是否存在 “ip:端口号”  (例如jdbc:redis://127.0.0.1:6379 )
        Pattern p = Pattern.compile("(\\d+\\.\\d+\\.\\d+\\.\\d+)\\:(\\d+)");
        Matcher m = p.matcher(s);
        HashMap<String,String>  map = new HashMap<>();
        //将符合规则的提取出来
        while(m.find()) {
            map.put("ip",m.group(1));
            map.put("port",m.group(2));
        }
        if(s.contains("redis")){
            map.put("index","0");
            int index = s.indexOf(map.get("port"));
            if (StringUtils.equals(map.get("port"), s.substring(index)) || StringUtils.equals(map.get("port").concat("/"), s.substring(index))) {
                throw new ServiceException("redis数据源url须指定数据库下标");
            } else if (StringUtils.isNotEmpty(s.substring(index + map.get("port").length() + 1))) {
                index = index + map.get("port").length() + 1;
                String dbIndex = s.substring(index);
                map.put("index", dbIndex);
            }
        }
        return map;
    }

    public static String setOrGetRedisByKey(ApiDatasource datasource, ApiConfig config) {
        if (datasource == null || config == null) {
            return null;
        }
        List<ApiSql> sqlList = config.getSqlList();
        if (sqlList.isEmpty()) {
            return null;
        }
        Jedis jedis = RedisPoolManager.getRedisPooledConnection(datasource);
        String sql = sqlList.get(0).getSqlText();
        String redisKey = sql.substring(sql.lastIndexOf(" ") + 1);
        if (sql.contains("set")) {
            jedis.set(redisKey, config.getJsonParam());
            return JSON.toJSONString(ResponseDto.apiSuccess("set key success"));
        } else {
            String redisVal = jedis.get(redisKey);
            return ResponseDto.apiSuccess(redisVal).toQueryString();
        }

    }
}
